import React, { useEffect, useState } from 'react'
import './index.css'
// @ts-expect-error 解决ts报错
import BorderBox10 from '@jiaminghi/data-view-react/es/borderBox1'
import { useNavigate } from 'react-router-dom'
import io from 'socket.io-client'
import Recorder from 'js-audio-recorder'
import axios from 'axios'
import MyHeader from '../../components/MyHeader/Index'
import { useSwitch } from '../../utils/useSwitch'
import { FloatButton } from 'antd'
import { ConsoleSqlOutlined } from '@ant-design/icons'
import Movement2 from '../../components/Movement2'
import Movement from '../../components/Movement'
// 聊天
import MyChat from '../../components/MyChat/Index'
// 底部
import MyFooter from '../../components/MyFooter/Index'

const Index: React.FC = () => {
  // 进入3D展馆
  const navigate = useNavigate()
  const gotothree = () => {
    navigate('/layout/exhibition')
  }

  // 切换主题 持久化
  const { state, toggle } = useSwitch()

  // 鼠标划入划出
  const [isHoverChat, setIsHoverChat] = useState<boolean>(true)
  const [isHoverAnswers, setIsHoverAnswers] = useState<boolean>(true)
  const handleChat = () => {
    setIsHoverChat(false)
  }
  const handleChat1 = () => {
    setIsHoverChat(true)
  }
  const handleAnswers = () => {
    setIsHoverAnswers(false)
  }
  const handleAnswers1 = () => {
    setIsHoverAnswers(true)
  }

  // 语音控制
  const [isTalk, setIsTalk] = useState<boolean>(true)
  const toggleTalk = () => {
    setIsTalk(!isTalk)
    Startend()
  }
  // 导入 React 库中的 useState 和 useEffect 钩子
  const [roomId, setrooId] = useState<number | string>('') // 定义 roomId 状态，初始值为空字符串
  const [ws, setWs] = useState(null) // 定义 ws 状态，用于存储 WebSocket 连接，初始值为 null
  const [recorder, setRecorder] = useState<Recorder | null>(null) // 定义 recorder 状态，用于存储录音器实例，初始值为 null
  const url = 'http://123.60.213.46:8811' // 定义 WebSocket 服务器的 URL
  const [T, setT] = useState<number | null>(null) // 定义 T 状态，用于存储定时器 ID，初始值为 null
  const [temp, setTemp] = useState('') // 定义 temp 状态，用于存储从服务器接收到的值，初始值为空字符串
  const [text, setText] = useState(false)
  const [aipower, setAipower] = useState('')
  const [isVoice, setIsVoice] = useState(true)
  const [num, setNum] = useState(0)
  const [isShow, setIsShow] = useState(false)
  const [array, setArray] = useState<
    { temp: string; user: string; img: string }[]
  >([])
  const [vioceText, setVioceText] = useState('')
  const [isText, setIsText] = useState(false)
  const [src] = useState(
    'http://zifan1998.oss-cn-beijing.aliyuncs.com/%E6%8A%96%E9%9F%B320241111-533667.mp4'
  )
  const [isLarge, setIsLarge] = useState('1')

  const handleLarge = (value: string) => {
    setIsLarge(value)
  }

  useEffect(() => {
    const socket = io(url) // 创建 WebSocket 连接
    // @ts-expect-error 解决ts报错
    setWs(socket) // 将 WebSocket 连接存储在 ws 状态中

    const T = new Date().getTime() // 获取当前时间戳
    setrooId(T) // 将时间戳存储在 roomId 状态中
    socket.emit('joinRoom', T)
    socket.on('value', val => {
      setTemp(val) // 将从服务器接收到的值存储在 temp 状态中
    })
    setRecorder(
      new Recorder({
        // @ts-expect-error 取消下一行报错
        bitRate: 16, // 设置录音比特率为 16 kbps
        sampleRate: 16000, // 设置录音采样率为 16000 Hz
        bufferSize: 8192 // 设置录音缓冲区大小为 8192 字节
      })
    )

    // 清理函数
    return () => {
      socket.disconnect() // 断开 WebSocket 连接
    }
  }, [url])

  const startR = () => {
    console.log('开始录音')
    setText(true)
    setIsShow(true)
    window.speechSynthesis.cancel() // 取消所有语音合成任务
    recorder?.start() // 开始录音

    const sendAudioData = () => {
      const pcmBlob = recorder?.getPCMBlob() // 获取录音的 PCM 数据

      const reader = new FileReader()
      reader.onload = () => {
        const arrayBuffer = reader.result as ArrayBuffer // 将 FileReader 的 result 转换为 ArrayBuffer
        const base64 = arrayBufferToBase64(arrayBuffer) // 将 ArrayBuffer 转换为 Base64 编码的字符串

        // 发送 Base64 编码的音频数据到服务器
        // @ts-expect-error 取消下一行报错
        ws?.emit('other', {
          roomId: roomId,
          value: base64 // 传递 base64 编码的音频数据
        })
      }
      reader.readAsArrayBuffer(pcmBlob) // 将 PCM 数据转换为 ArrayBuffer
    }

    const intervalId = setInterval(sendAudioData, 200) // 每隔200毫秒发送一次音频数据
    setT(intervalId) // 将定时器 ID 存储在 T 状态中
  }

  // 停止录音
  const stopR = () => {
    setText(false)
    clearInterval(T!) // 清除定时器
    setT(null) // 将 T 状态重置为 null
    recorder?.stop() // 停止录音
    localStorage.setItem('ss', temp) // 将 temp 状态的值存储在 localStorage 中
    setArray([
      ...array,
      {
        temp: temp,
        user: 'user',
        img: 'https://img2.baidu.com/it/u=1090452517,2487311686&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1732726800&t=83aec6c8fc27927432503a421661536c'
      },
      {
        temp: '整理语言中....',
        user: 'ai',
        img: 'https://img1.baidu.com/it/u=2743394743,692629981&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1732726800&t=4e8c52623a39fab7d619c71a5daa4f37'
      }
    ])
    sendDataToBackend(temp)
  }

  // 将 ArrayBuffer 转换为 Base64 编码的字符串
  function arrayBufferToBase64(buffer: ArrayBuffer) {
    let binary = ''
    const bytes = new Uint8Array(buffer)
    const len = bytes.byteLength
    for (let i = 0; i < len; i++) {
      binary += String.fromCharCode(bytes[i])
    }
    return window.btoa(binary) // 将二进制字符串转换为 base64 编码
  }

  const Startend = () => {
    if (!text) {
      startR()
      return
    } else {
      stopR()
      return
    }
  }
  // 语音回话功能
  useEffect(() => {
    const utterance = new SpeechSynthesisUtterance(aipower)
    utterance.onstart = () => {
      setIsText(true)
    }
    window.speechSynthesis.speak(utterance)
    utterance.onend = () => {
      setIsText(false)
    }
    setArray([
      ...array.filter(item => item.temp !== '整理语言中....'),
      {
        temp: aipower,
        user: 'ai',
        img: 'https://img1.baidu.com/it/u=2743394743,692629981&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1732726800&t=4e8c52623a39fab7d619c71a5daa4f37'
      }
    ])
  }, [num, aipower])

  // 文字转语音
  const speak = () => {
    if (temp) {
      const utterance = new SpeechSynthesisUtterance(temp)
      window.speechSynthesis.speak(utterance)
    }
  }

  const sendDataToBackend = async (temp: string) => {
    let router: string
    if (isLarge === '1') {
      router = '/api/users'
    } else {
      router = '/api/users/qian'
    }
    const res = await axios.post(router, { temp })
    console.log(res)
    if (res.data.code === 200) {
      setAipower(res.data.role)
    } else {
      setAipower(res.data.msg)
    }
    setNum(num + 1)
  }

  // 切换输入模式
  const toggleVoice = () => {
    setIsVoice(!isVoice)
  }

  // 文字输入
  const handleTextChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setVioceText(e.target.value)
  }
  const textAi = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.code === 'Enter') {
      window.speechSynthesis.cancel() // 取消所有语音合成任务
      setArray([
        ...array,
        {
          temp: (e.target as HTMLInputElement).value,
          user: 'user',
          img: 'https://img2.baidu.com/it/u=1090452517,2487311686&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1732726800&t=83aec6c8fc27927432503a421661536c'
        },
        {
          temp: '整理语言中....',
          user: 'ai',
          img: 'https://img1.baidu.com/it/u=2743394743,692629981&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1732726800&t=4e8c52623a39fab7d619c71a5daa4f37'
        }
      ])
      sendDataToBackend((e.target as HTMLInputElement).value)
      setVioceText('')
      setIsShow(true)
    }
  }

  return (
    <div className="box">
      {/* 头部 */}
      <MyHeader state={state} gotothree={gotothree} toggle={toggle}></MyHeader>
      {/* 中间 */}
      <main>
        {/* 机器人 */}
        <div className="left">{isText ? <Movement /> : <Movement2 />}</div>
        {/* 视频 */}
        <div className="rigth">
          <div className="bell">
            <p>呼唤&quot;子凡 子凡&quot;，开启新一轮对话</p>
            <img onClick={speak} src="../src/assets/image/notice.gif" alt="" />
          </div>
          <BorderBox10>
            {/* 视频或聊天 */}
            <MyChat src={src} state={state} isShow={isShow} array={array} />
            {/* 切换视频或聊天 */}
            <FloatButton
              icon={<ConsoleSqlOutlined />}
              description="切换"
              type="primary"
              shape="square"
              style={{
                position: 'absolute',
                bottom: '-10px',
                right: '10px'
              }}
              onClick={() => setIsShow(!isShow)}
            />
          </BorderBox10>
        </div>
      </main>
      {/* 尾部 */}
      <MyFooter
        isTalk={isTalk}
        isLarge={isLarge}
        handleLarge={handleLarge}
        isHoverChat={isHoverChat}
        isHoverAnswers={isHoverAnswers}
        toggleTalk={toggleTalk}
        handleChat={handleChat}
        handleChat1={handleChat1}
        handleAnswers={handleAnswers}
        handleAnswers1={handleAnswers1}
        toggle={toggle}
        isVoice={isVoice}
        toggleVoice={toggleVoice}
        textAi={textAi}
        vioceText={vioceText}
        handleTextChange={handleTextChange}
      />
    </div>
  )
}

export default Index
